﻿/* 2013/1/6 */
using System;
using System.Text;
using System.IO;

namespace Cosmos.Media
{
    /// <summary>
    /// Provides instance properties for getting information of MP3 file.
    /// </summary>
    public sealed class Mp3Info
    { 
        #region Fields

        /// <summary>
        /// File name of the MP3 file.
        /// </summary>
        private string _fileName;

        /// <summary>
        /// File path of the MP3 file.
        /// </summary>
        private string _filePath;

        /// <summary>
        /// A character encoding used to convert binary information to string.
        /// </summary>
        private Encoding _encoding;

        private ID3V1 _id3v1;

        private ID3V2Header _id3v2Header;

        private ID3V2 _id3v2;

        #endregion

        /// <summary>
        /// Initializes an instance of Mp3Info class with specified file path.
        /// </summary>
        /// <param name="mp3FilePath"></param>
        public Mp3Info(string mp3FilePath)
        {
            FileInfo fileInfo = new FileInfo(mp3FilePath);
            _fileName = fileInfo.Name;
            _filePath = fileInfo.FullName;

            _encoding = Encoding.Default;
            
            if (fileInfo.Exists)
            {
                getInfoBytes(mp3FilePath);
            }
        }

        /// <summary> 
        /// Gets information bytes, which are the last 128 bytes of the MP3 file.
        /// </summary> 
        /// <param name="filePath">The path of MP3 file.</param> 
        private void getInfoBytes(string filePath)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            int byteCount = 0;
            
            fs.Seek(0, SeekOrigin.Begin);
            byte[] id3v2HeaderBytes = new byte[ID3V2Header.TotalLength];
            byteCount = fs.Read(id3v2HeaderBytes, 0, ID3V2Header.TotalLength);
            if (byteCount == ID3V2Header.TotalLength)
            {
                _id3v2Header = new ID3V2Header();
                _id3v2Header.Load(id3v2HeaderBytes);
            }

            if (_id3v2Header.isAvailable)
            {
                int allFrameSize = _id3v2Header.AllFrameSize;
                byte[] id3v2FrameBytes = new byte[allFrameSize];
                byteCount = fs.Read(id3v2FrameBytes, 0, allFrameSize);
                if (byteCount == allFrameSize)
                {

                    _id3v2 = new ID3V2();
                    _id3v2.Load(id3v2FrameBytes);
                }
            }

            fs.Seek(-ID3V1.TotalLength, SeekOrigin.End);
            byte[] id3v1Bytes = new byte[ID3V1.TotalLength];
            byteCount = fs.Read(id3v1Bytes, 0, ID3V1.TotalLength);
            if (byteCount == ID3V1.TotalLength)
            {
                _id3v1 = new ID3V1();
                _id3v1.Load(id3v1Bytes);
            }

            fs.Close();
        } 

        /// <summary>
        /// Converts an array of bytes to a string.
        /// </summary> 
        /// <param name = "bytes">An byte array.</param> 
        /// <returns>A string converted from the bytes.</returns>
        private string DecodeByte(byte[] bytes)
        {
            if (bytes == null)
            {
                return String.Empty;
            }

            string str = _encoding.GetString(bytes);
            //str = str.Substring(0, str.IndexOf("#CONTENT#") >= 0 ? str.IndexOf("#CONTENT#") : str.Length);//去掉无用字符             
            return str;
        }

        #region Propreties

        public string FileName
        {
            get
            { 
                return _fileName; 
            }
        }

        public string FilePath
        {
            get
            { 
                return _filePath; 
            }
        }

        public string ID3V1Title
        {
            get 
            {
                return DecodeByte(_id3v1.Title);
            }
        }

        public string ID3V1Artist
        {
            get
            {
                return DecodeByte(_id3v1.Artist);
            }
        }

        public string ID3V1Album
        {
            get 
            {
                return DecodeByte(_id3v1.Album);
            }
        }

        public string ID3V1Year
        {
            get
            {
                return DecodeByte(_id3v1.Year);
            }
        }

        public string ID3V1Comment
        {
            get 
            {
                return DecodeByte(_id3v1.Comment);
            }
        }

        public string ID3V2Title
        {
            get
            {
                return DecodeByte(_id3v2.Title);
            }
        }

        public string ID3V2Artist
        {
            get
            {
                return DecodeByte(_id3v2.Artist);
            }
        }

        public string ID3V2Album
        {
            get
            {
                return DecodeByte(_id3v2.Album);
            }
        }

        public string ID3V2Year
        {
            get
            {
                return DecodeByte(_id3v2.Year);
            }
        }

        public string ID3V2Comment
        {
            get
            {
                return DecodeByte(_id3v2.Comment);
            }
        }

        public string Encode
        {
            get
            {
                return _encoding.EncodingName;
            }

            set
            {
                _encoding = Encoding.GetEncoding(value);
            }
        }

        #endregion
    }
}


/*
0="Blues";
1="ClassicRock";
2="Country";
3="Dance";
4="Disco";
5="Funk";
6="Grunge";
7="Hip-Hop";
8="Jazz";
9="Metal";
10="NewAge";
11="Oldies";
12="Other";
13="Pop";
14="R&B";
15="Rap";
16="Reggae";
17="Rock";
18="Techno";
19="Industrial";
20="Alternative";
21="Ska";
22="DeathMetal";
23="Pranks";
24="Soundtrack";
25="Euro-Techno";
26="Ambient";
27="Trip-Hop";
28="Vocal";
29="Jazz+Funk";
30="Fusion";
31="Trance";
32="Classical";
33="Instrumental";
34="Acid";
35="House";
36="Game";
37="SoundClip";
38="Gospel";
39="Noise";
40="AlternRock";
41="Bass";
42="Soul";
43="Punk";
44="Space";
45="Meditative";
46="InstrumentalPop";
47="InstrumentalRock";
48="Ethnic";
49="Gothic";
50="Darkwave";
51="Techno-Industrial";
52="Electronic";
53="Pop-Folk";
54="Eurodance";
55="Dream";
56="SouthernRock";
57="Comedy";
58="Cult";
59="Gangsta";
60="Top40";
61="ChristianRap";
62="Pop/Funk";
63="Jungle";
64="NativeAmerican";
65="Cabaret";
66="NewWave";
67="Psychadelic";
68="Rave";
69="Showtunes";
70="Trailer";
71="Lo-Fi";
72="Tribal";
73="AcidPunk";
74="AcidJazz";
75="Polka";
76="Retro";
77="Musical";
78="Rock&Roll";
79="HardRock";

80="Folk";
81="Folk-Rock";
82="NationalFolk";
83="Swing";
84="FastFusion";
85="Bebob";
86="Latin";
87="Revival";
88="Celtic";
89="Bluegrass";
90="Avantgarde";
91="GothicRock";
92="ProgessiveRock";
93="PsychedelicRock";
94="SymphonicRock";
95="SlowRock";
96="BigBand";
97="Chorus";
98="EasyListening";
99="Acoustic";
100="Humour";
101="Speech";
102="Chanson";
103="Opera";
104="ChamberMusic";
105="Sonata";
106="Symphony";
107="BootyBass";
108="Primus";
109="PornGroove";
110="Satire";
111="SlowJam";
112="Club";
113="Tango";
114="Samba";
115="Folklore";
116="Ballad";
117="PowerBallad";
118="RhythmicSoul";
119="Freestyle";
120="Duet";
121="PunkRock";
122="DrumSolo";
123="Acapella";
124="Euro-House";
125="DanceHall";
126="Goa";
127="Drum&Bass";
128="Club-House";
129="Hardcore";
130="Terror";
131="Indie";
132="BritPop";
133="Negerpunk";
134="PolskPunk";
135="Beat";
136="ChristianGangstaRap";
137="HeavyMetal";
138="BlackMetal";
139="Crossover";
140="ContemporaryChristian";
141="ChristianRock";
142="Merengue";
143="Salsa";
144="TrashMetal";
145="Anime";
146="JPop";
147="Synthpop"; 
*/
